#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define MAXDATASIZE 100 // max number of bytes we can get at once
#define MAX_MSG_LEN 256

int sendall(int s, char *buf, int *len);
void readBuffer(char *buffer, int bufLen);

int main(int argc, char **argv){
	int sockfd;     // listening socket descriptor
	char *PORT, buf[MAX_MSG_LEN];

	socklen_t addrlen;

	int yes=1;        // for setsockopt() SO_REUSEADDR, below
	int rv, numbytes;

	struct addrinfo hints, *ai;

	if (argc != 2){
		fprintf(stdout, "ERROR: please enter port number as an argument\n");
		return 0;
	}

	PORT = argv[1];

	memset(&hints, 0, sizeof hints);
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;
	if ((rv = getaddrinfo("127.0.0.1", PORT, &hints, &ai)) != 0) {
		fprintf(stderr, "ERROR: %s\n", gai_strerror(rv));   //rv is just for error ref.
		return 0;
	}

	sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
	if (sockfd < 0){
		fprintf(stdout, "ERROR: couldn't get a socket from the OS!!\n");
		freeaddrinfo(ai); // all done with this
		return 0;
	}

	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));

	if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) == -1) {
		close(sockfd);
		fprintf(stdout, "failed to connect to server\n");
		return 0;
	}

	freeaddrinfo(ai); // all done with this

	printf("you are now connected\n\n");

	while(1){
		printf(">>");
		readBuffer(buf, MAX_MSG_LEN);   //DEBUG: replace with the readbuffer function
		numbytes = strlen(buf);
		if (sendall(sockfd, buf, &numbytes) == -1){
			fprintf(stdout, "ERROR: failed to send the whole buffer\n"
					"sent only %d bytes out of %d, \n", numbytes, (int)strlen(buf));
		}
		if (strcmp("exit", buf) == 0){
			break;
		}
	}

	printf("exiting echoClient\n");
	close(sockfd);
	return 1;
}


/*beej's function: wrapping a send() function to make sure big buffers
 * are sent properly
 */
int sendall(int s, char *buf, int *len)
{
	int total = 0;        // how many bytes we've sent
	int bytesleft = *len; // how many we have left to send
	int n;

	while(total < *len) {
		n = send(s, buf+total, bytesleft, 0);
		if (n == -1) { break; }
		total += n;
		bytesleft -= n;
	}

	*len = total; // return number actually sent here

	return n==-1?-1:0; // return -1 on failure, 0 on success
}

void readBuffer(char *buffer, int bufLen){
	char c = 0, *p;
	int charCount = 0;

	p = buffer;
	while (charCount != bufLen-1 && (c = getchar()) != '\n'){
		*p = c;
		p++;
	}
	p[charCount] = '\0';
	return;
}
